package org.Yiran.timetale_re.item.tool.screwdriver.modules.container;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.IModule;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.Modules;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.enmu.ModuleCategory;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.enmu.ModuleType;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 工具模块容器
 * <p>
 * 管理工具中的模块，支持添加、移除和获取模块
 * </p>
 */
public class ToolModuleContainer {
    
    private static final String MODULES_TAG = "Modules";
    private static final String MODULE_ID_TAG = "ModuleId";
    private static final String ACTIVE_FUNCTION_MODULE_TAG = "ActiveFunctionModule";
    
    private final List<IModule> modules = new ArrayList<>();
    private final int maxModules;
    private String activeFunctionModuleId = null; // 当前激活的功能模块ID
    
    /**
     * 工具模块容器构造函数
     *
     * @param maxModules 最大模块数量
     */
    public ToolModuleContainer(int maxModules) {
        // 确保最大模块数量不为负数
        this.maxModules = Math.max(0, maxModules);
    }
    
    /**
     * 从物品栈中加载模块
     *
     * @param stack 物品栈
     */
    public void loadFromItemStack(ItemStack stack) {
        this.modules.clear();
        
        if (shouldLoadModulesFromStack(stack)) {
            loadModulesFromStack(stack);
        }
    }
    
    /**
     * 检查是否应该从物品栈加载模块
     * <p>
     * 验证物品栈是否包含模块数据
     * </p>
     *
     * @param stack 物品栈
     * @return 如果应该加载模块返回true，否则返回false
     */
    private boolean shouldLoadModulesFromStack(ItemStack stack) {
        return stack.hasTag();
    }
    
    /**
     * 从物品栈加载模块
     * <p>
     * 解析物品栈中的NBT数据并加载模块
     * </p>
     *
     * @param stack 物品栈
     */
    private void loadModulesFromStack(ItemStack stack) {
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(MODULES_TAG, Tag.TAG_LIST)) {
            ListTag modulesList = tag.getList(MODULES_TAG, Tag.TAG_COMPOUND);
            processModuleList(modulesList);
            
            // 加载激活的功能模块ID
            if (tag.contains(ACTIVE_FUNCTION_MODULE_TAG)) {
                this.activeFunctionModuleId = tag.getString(ACTIVE_FUNCTION_MODULE_TAG);
            }
        }
    }
    
    /**
     * 处理模块列表
     * <p>
     * 遍历模块列表并添加到容器中
     * </p>
     *
     * @param modulesList 模块列表标签
     */
    private void processModuleList(ListTag modulesList) {
        for (int i = 0; i < modulesList.size(); i++) {
            CompoundTag moduleTag = modulesList.getCompound(i);
            String moduleId = moduleTag.getString(MODULE_ID_TAG);
            Modules.getModule(moduleId).ifPresent(this.modules::add);
        }
    }
    
    /**
     * 保存模块到物品栈
     *
     * @param stack 物品栈
     */
    public void saveToItemStack(ItemStack stack) {
        if (!this.modules.isEmpty()) {
            saveModulesToStack(stack);
        } else if (stack.hasTag()) {
            removeModulesFromStack(stack);
        }
    }
    
    /**
     * 将模块保存到物品栈
     * <p>
     * 将容器中的所有模块序列化并保存到物品栈的NBT数据中
     * </p>
     *
     * @param stack 物品栈
     */
    private void saveModulesToStack(ItemStack stack) {
        CompoundTag tag = stack.getOrCreateTag();
        ListTag modulesList = createModulesList();
        tag.put(MODULES_TAG, modulesList);
        
        // 保存激活的功能模块ID
        if (this.activeFunctionModuleId != null) {
            tag.putString(ACTIVE_FUNCTION_MODULE_TAG, this.activeFunctionModuleId);
        }
    }
    
    /**
     * 创建模块列表
     * <p>
     * 将容器中的所有模块转换为NBT标签列表
     * </p>
     *
     * @return 模块列表标签
     */
    private ListTag createModulesList() {
        ListTag modulesList = new ListTag();
        
        for (IModule module : this.modules) {
            CompoundTag moduleTag = new CompoundTag();
            moduleTag.putString(MODULE_ID_TAG, module.getModuleId());
            modulesList.add(moduleTag);
        }
        
        return modulesList;
    }
    
    /**
     * 从物品栈中移除模块数据
     * <p>
     * 当容器中没有模块时，从物品栈的NBT数据中移除模块标签
     * </p>
     *
     * @param stack 物品栈
     */
    private void removeModulesFromStack(ItemStack stack) {
        // 如果没有模块，移除NBT标签
        CompoundTag tag = stack.getTag();
        if (tag != null) {
            tag.remove(MODULES_TAG);
            tag.remove(ACTIVE_FUNCTION_MODULE_TAG);
        }
        if (tag != null && tag.isEmpty()) {
            stack.setTag(null);
        }
    }
    
    /**
     * 添加模块
     *
     * @param module 模块
     * @return 是否添加成功
     */
    public boolean addModule(IModule module) {
        // 检查模块是否有效
        if (!isModuleValid(module)) {
            return false;
        }
        
        if (canAddModule(module)) {
            boolean added = this.modules.add(module);
            // 如果添加的是功能模块且当前没有激活的功能模块，则将其设为激活状态
            if (added && module.getModuleCategory() == ModuleCategory.FUNCTION && this.activeFunctionModuleId == null) {
                this.activeFunctionModuleId = module.getModuleId();
            }
            return added;
        }
        return false;
    }
    
    /**
     * 检查模块是否有效
     * <p>
     * 验证模块及其ID是否有效
     * </p>
     *
     * @param module 模块
     * @return 如果模块有效返回true，否则返回false
     */
    private boolean isModuleValid(IModule module) {
        return module != null && module.getModuleId() != null && !module.getModuleId().isEmpty();
    }
    
    /**
     * 检查是否可以添加模块
     * <p>
     * 检查容器是否未满且不包含相同ID或类型的模块
     * </p>
     *
     * @param module 模块
     * @return 如果可以添加模块返回true，否则返回false
     */
    private boolean canAddModule(IModule module) {
        // 基本检查：容器未满，不包含相同ID的模块，不包含相同类型的模块
        return this.modules.size() < this.maxModules && 
               !this.hasModule(module.getModuleId()) && 
               !this.hasModuleOfType(module.getModuleType());
    }
    
    /**
     * 移除模块
     *
     * @param moduleId 模块ID
     * @return 被移除的模块的Optional
     */
    public Optional<IModule> removeModule(String moduleId) {
        Optional<IModule> module = this.getModule(moduleId);
        return module.flatMap(this::removeModuleFromContainer);
    }
    
    /**
     * 从容器中移除模块
     * <p>
     * 从模块列表中移除指定的模块并返回它
     * </p>
     *
     * @param module 要移除的模块
     * @return 被移除的模块
     */
    private Optional<IModule> removeModuleFromContainer(IModule module) {
        boolean removed = this.modules.remove(module);
        if (removed) {
            // 如果移除的是当前激活的功能模块，则清除激活状态
            if (module.getModuleCategory() == ModuleCategory.FUNCTION && 
                module.getModuleId().equals(this.activeFunctionModuleId)) {
                this.activeFunctionModuleId = null;
            }
            return Optional.of(module);
        }
        return Optional.empty();
    }
    
    /**
     * 获取模块
     *
     * @param moduleId 模块ID
     * @return 模块的Optional
     */
    public Optional<IModule> getModule(String moduleId) {
        if (isModuleIdValid(moduleId)) {
            return Optional.empty();
        }
        
        return findModuleById(moduleId);
    }
    
    /**
     * 检查模块ID是否有效
     * <p>
     * 验证模块ID是否不为null且不为空
     * </p>
     *
     * @param moduleId 模块ID
     * @return 如果模块ID有效返回true，否则返回false
     */
    private boolean isModuleIdValid(String moduleId) {
        return moduleId == null || moduleId.isEmpty();
    }
    
    /**
     * 根据ID查找模块
     * <p>
     * 在模块列表中查找具有指定ID的模块
     * </p>
     *
     * @param moduleId 模块ID
     * @return 找到的模块的Optional
     */
    private Optional<IModule> findModuleById(String moduleId) {
        return this.modules.stream()
            .filter(m -> m.getModuleId() != null && m.getModuleId().equals(moduleId))
            .findFirst();
    }
    
    /**
     * 检查是否已包含指定模块
     *
     * @param moduleId 模块ID
     * @return 是否包含
     */
    public boolean hasModule(String moduleId) {
        if (isModuleIdValid(moduleId)) {
            return false;
        }
        return isModulePresent(moduleId);
    }
    
    /**
     * 检查模块是否存在
     * <p>
     * 检查具有指定ID的模块是否存在于容器中
     * </p>
     *
     * @param moduleId 模块ID
     * @return 如果模块存在返回true，否则返回false
     */
    private boolean isModulePresent(String moduleId) {
        return this.getModule(moduleId).isPresent();
    }
    
    /**
     * 检查是否已包含指定类型的模块
     *
     * @param moduleType 模块类型
     * @return 是否包含
     */
    public boolean hasModuleOfType(ModuleType moduleType) {
        if (!isModuleTypeValid(moduleType)) {
            return false;
        }
        return checkForModuleType(moduleType);
    }
    
    /**
     * 检查模块类型是否有效
     * <p>
     * 验证模块类型是否不为null
     * </p>
     *
     * @param moduleType 模块类型
     * @return 如果模块类型有效返回true，否则返回false
     */
    private boolean isModuleTypeValid(ModuleType moduleType) {
        return moduleType != null;
    }
    
    /**
     * 检查是否存在指定类型的模块
     * <p>
     * 在模块列表中检查是否存在指定类型的模块
     * </p>
     *
     * @param moduleType 模块类型
     * @return 如果存在指定类型的模块返回true，否则返回false
     */
    private boolean checkForModuleType(ModuleType moduleType) {
        return this.modules.stream()
            .anyMatch(m -> m.getModuleType() != null && moduleType.equals(m.getModuleType()));
    }
    
    /**
     * 获取所有模块
     *
     * @return 模块列表
     */
    public List<IModule> getModules() {
        return new ArrayList<>(this.modules);
    }
    
    /**
     * 根据模块分类获取模块
     *
     * @param category 模块分类
     * @return 指定分类的模块列表
     */
    public List<IModule> getModulesByCategory(ModuleCategory category) {
        return this.modules.stream()
                .filter(module -> category.equals(module.getModuleCategory()))
                .collect(Collectors.toList());
    }
    
    /**
     * 获取模块按分类分组
     *
     * @return 按分类分组的模块映射
     */
    public Map<ModuleCategory, List<IModule>> getModulesByCategory() {
        return this.modules.stream()
                .collect(Collectors.groupingBy(IModule::getModuleCategory));
    }
    
    /**
     * 获取模块数量
     *
     * @return 模块数量
     */
    public int getModuleCount() {
        return this.modules.size();
    }
    
    /**
     * 获取指定分类的模块数量
     *
     * @param category 模块分类
     * @return 指定分类的模块数量
     */
    public int getModuleCountByCategory(ModuleCategory category) {
        return (int) this.modules.stream()
                .filter(module -> category.equals(module.getModuleCategory()))
                .count();
    }
    
    /**
     * 获取最大模块数量
     *
     * @return 最大模块数量
     */
    public int getMaxModules() {
        return this.maxModules;
    }
    
    /**
     * 检查是否已满
     *
     * @return 是否已满
     */
    public boolean isFull() {
        // 防止除以零错误，确保最大模块数至少为1
        return this.modules.size() >= getEffectiveMaxModules();
    }
    
    /**
     * 获取有效的最大模块数量
     * <p>
     * 确保最大模块数至少为1，防止除以零错误
     * </p>
     *
     * @return 有效的最大模块数量
     */
    private int getEffectiveMaxModules() {
        return Math.max(1, this.maxModules);
    }
    
    /**
     * 设置当前激活的功能模块
     *
     * @param moduleId 模块ID
     * @return 是否设置成功
     */
    public boolean setActiveFunctionModule(String moduleId) {
        // 检查模块是否存在且是功能模块
        Optional<IModule> moduleOpt = getModule(moduleId);
        if (moduleOpt.isPresent() && moduleOpt.get().getModuleCategory() == ModuleCategory.FUNCTION) {
            this.activeFunctionModuleId = moduleId;
            return true;
        }
        return false;
    }
    
    /**
     * 获取当前激活的功能模块
     *
     * @return 当前激活的功能模块的Optional
     */
    public Optional<IModule> getActiveFunctionModule() {
        if (this.activeFunctionModuleId != null) {
            return getModule(this.activeFunctionModuleId);
        }
        // 如果没有设置激活的功能模块，但存在功能模块，则返回第一个功能模块
        return this.modules.stream()
                .filter(module -> module.getModuleCategory() == ModuleCategory.FUNCTION)
                .findFirst();
    }
    
    /**
     * 获取当前激活的功能模块ID
     *
     * @return 当前激活的功能模块ID
     */
    public String getActiveFunctionModuleId() {
        return this.activeFunctionModuleId;
    }
}